﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Common.Security
{
    /// <summary>
    /// Base64编码帮助类
    /// </summary>
    public class Base64Helper
    {
        static string codeTable = "UVJKL34WXYZbacDEI5MNO9PQRu*wxSTk678lmnopdef-ghijFGrACHqst1B_2yz0";
        static string pad = "&";
        static Dictionary<int, char> dt1 = new Dictionary<int, char>();
        static Dictionary<char, int> dt2 = new Dictionary<char, int>();

        static Base64Helper()
        {
            dt2.Add( pad[ 0 ], -1 );
            for( int i = 0; i < codeTable.Length; i++ )
            {
                dt1.Add( i, codeTable[ i ] );
                dt2.Add( codeTable[ i ], i );
            }
        }

        /// <summary>
        /// 对字符串进行加密
        /// </summary>
        /// <param name="source">字符串</param>
        /// <returns></returns>
        public static string Encode( string source )
        {
            if( string.IsNullOrEmpty( source ) )
            {
                return "";
            }
            StringBuilder stringBuilder = new StringBuilder();
            byte[] bytes = Encoding.UTF8.GetBytes( source );
            int num = bytes.Length % 3;
            int num2 = 3 - num;
            if( num != 0 )
            {
                Array.Resize<byte>( ref bytes, bytes.Length + num2 );
            }
            int num3 = ( int ) Math.Ceiling( ( double ) bytes.Length * 1.0 / 3.0 );
            for( int i = 0; i < num3; i++ )
            {
                stringBuilder.Append( EncodeUnit( new byte[]
				{
					bytes[i * 3],
					bytes[i * 3 + 1],
					bytes[i * 3 + 2]
				} ) );
            }
            if( num != 0 )
            {
                stringBuilder.Remove( stringBuilder.Length - num2, num2 );
                for( int j = 0; j < num2; j++ )
                {
                    stringBuilder.Append( pad );
                }
            }
            return stringBuilder.ToString();
        }

        static string EncodeUnit( params byte[] unit )
        {
            int[] array = new int[]
			{
				(unit[0] & 252) >> 2,
				((int)(unit[0] & 3) << 4) + ((unit[1] & 240) >> 4),
				((int)(unit[1] & 15) << 2) + ((unit[2] & 192) >> 6),
				(int)(unit[2] & 63)
			};
            StringBuilder stringBuilder = new StringBuilder();
            int[] array2 = array;
            for( int i = 0; i < array2.Length; i++ )
            {
                int code = array2[ i ];
                stringBuilder.Append( GetEC( code ) );
            }
            return stringBuilder.ToString();
        }

        /// <summary>
        /// 对字符串进行解密
        /// </summary>
        /// <param name="source">字符串</param>
        /// <returns></returns>
        public static string Decode( string source )
        {
            if( string.IsNullOrEmpty( source ) )
            {
                return "";
            }
            List<byte> list = new List<byte>();
            char[] array = source.ToCharArray();
            int num = array.Length % 4;
            if( num != 0 )
            {
                Array.Resize<char>( ref array, array.Length - num );
            }
            int num2 = source.IndexOf( pad );
            if( num2 != -1 )
            {
                num2 = source.Length - num2;
            }
            int num3 = array.Length / 4;
            for( int i = 0; i < num3; i++ )
            {
                DecodeUnit( list, new char[]
				{
					array[i * 4],
					array[i * 4 + 1],
					array[i * 4 + 2],
					array[i * 4 + 3]
				} );
            }
            for( int j = 0; j < num2; j++ )
            {
                list.RemoveAt( list.Count - 1 );
            }
            return Encoding.UTF8.GetString( list.ToArray() );
        }

        static void DecodeUnit( List<byte> byteArr, params char[] chArray )
        {
            int[] array = new int[ 3 ];
            byte[] array2 = new byte[ chArray.Length ];
            for( int i = 0; i < chArray.Length; i++ )
            {
                array2[ i ] = FindChar( chArray[ i ] );
            }
            array[ 0 ] = ( ( int ) array2[ 0 ] << 2 ) + ( ( array2[ 1 ] & 48 ) >> 4 );
            array[ 1 ] = ( ( int ) ( array2[ 1 ] & 15 ) << 4 ) + ( ( array2[ 2 ] & 60 ) >> 2 );
            array[ 2 ] = ( ( int ) ( array2[ 2 ] & 3 ) << 6 ) + ( int ) array2[ 3 ];
            byteArr.AddRange(
                from t in array
                select ( byte ) t );
        }

        static char GetEC( int code )
        {
            return dt1[ code ];
        }

        static byte FindChar( char ch )
        {
            int num = dt2[ ch ];
            return ( byte ) num;
        }

        void test()
        {
            string to = Base64Helper.Encode( "蔡壮茂&123" );
            string to2 = Base64Helper.Decode( to );
            Console.WriteLine( to );
            Console.WriteLine( to2 );
            Console.WriteLine( Base64Helper.Encode( "abcd'efg&123" ) );
        }
    }
}
